#include "stdafx.h"
#include <vex.tests/msperf/tests.exe/Perf_test_runner_ref_counting.h>
#include <vex/core/make_intrusive_handle.h>

namespace tests_exe { namespace ref_counting {
#ifdef _DEBUG
        const std::size_t s_run_count = 100u;
#else
        const std::size_t s_run_count = 1000000u;
#endif
        namespace {
            class VEX_ABSTRACT test_handle : public vex::core::contract::handle {};

            template<class TMemoryTag>
            static vex::core::contract::handle* internal_generate()
            {
                return vex::core::make_raw_handle_ext< test_handle >(TMemoryTag());
            }

            template<class THandle>
            static void internal_execute(THandle* p_handle)
            {
                for (std::size_t t_i = 0u; t_i < s_run_count; ++t_i) {
                    p_handle->add_ref();
                    p_handle->release();
                }
            }
        }

        class VEX_ABSTRACT Perf_test_runner_ref_counting_shared_sync : public Perf_test_runner_base {
        public:
            virtual const char* name() const
            {
                return "ref_counting_shared_sync";
            }

            virtual void run()
            {
                if (auto h = internal_generate<vex::core::handle_shared_sync_tag>()) {
                    auto t = boost::chrono::high_resolution_clock::now();
                    ref_counting::internal_execute(h);
                    set_duration_ticks((boost::chrono::high_resolution_clock::now() - t).count());
                    h->release();
                }
            }
        };

        class VEX_ABSTRACT Perf_test_runner_ref_counting_shared : public Perf_test_runner_base {
        public:
            virtual const char* name() const
            {
                return "ref_counting_shared";
            }

            virtual void run()
            {
                if (auto h = internal_generate<vex::core::handle_shared_tag>()) {
                    auto t = boost::chrono::high_resolution_clock::now();
                    ref_counting::internal_execute(h);
                    set_duration_ticks((boost::chrono::high_resolution_clock::now() - t).count());
                    h->release();
                }
            }
        };

        void append_your_runners(Iperf_test_runner_collector* p_runners)
        {
            if (p_runners) {
                if (auto p = vex::core::make_intrusive_handle<Perf_test_runner_ref_counting_shared>()) {
                    p_runners->put(p.get());
                }

                if (auto p = vex::core::make_intrusive_handle<Perf_test_runner_ref_counting_shared_sync>()) {
                    p_runners->put(p.get());
                }
            }
        }
}}